import java.lang.Math;

public class Fabrik extends Thread{
	
	/*
	 * Unsere Verpackungsmaschinen
	 */
	public Verpackungsmaschine v1;
	public Verpackungsmaschine v2;
	
	/*
	 * Schleifmaschinen
	 */
	public Schleifmaschine s1;
	public Schleifmaschine s2;
	public Schleifmaschine s3;
	public Schleifmaschine s4;
	public Schleifmaschine s5;

	/*
	 * Und eine zerteilmaschine
	 */
	public Zerteilmaschine z1;
	
	//Unser Holz das wir zur verfuegung ham//
	private int holz = 0;
	
	//Behaelter//
	private Container roh; 
	
	private Container geschliffen;
	
	private Container verpackt;
	
	/*Konstruktor mit Runtimes*/
	
	public Fabrik(int holz, int Zerteilruntime, int Verpackungsruntime1,int Verpackungsruntime2, int Schleifruntime1, int Schleifruntime2, int Schleifruntime3, int Schleifruntime4, int Schleifruntime5,int Containergroesse1,int Containergroesse2)
	{
		//Maschinen init
		this.v1 = new Verpackungsmaschine(Verpackungsruntime1, this);
		this.v2 = new Verpackungsmaschine(Verpackungsruntime2, this);
		
		this.s1 = new Schleifmaschine(Schleifruntime1, this);
		this.s2 = new Schleifmaschine(Schleifruntime2, this);
		this.s3 = new Schleifmaschine(Schleifruntime3, this);
		this.s4 = new Schleifmaschine(Schleifruntime4, this);
		this.s5 = new Schleifmaschine(Schleifruntime5, this);
		
		this.z1 = new Zerteilmaschine(Zerteilruntime, this);
		
		//Container init
		this.verpackt = new Container((holz*5));
		this.roh = new Container(Containergroesse1);
		this.geschliffen = new Container(Containergroesse2);
		
		//Anzahl der holzstuecke
		this.holz = holz;
	}

	//Run des Threads
	public void run()
	{
		//Starte Maschinen
		this.v1.start();
		this.v2.start();
				
		this.s1.start();
		this.s2.start();
		this.s3.start();
		this.s4.start();
		this.s5.start();

		this.z1.start();
		
		//Berechnen der Runtime: ergibt sich aus den einzelnen Runtimes und der Anzahlt der Holzstuecke die verarbeitet werden koennen
		int waittime = this.holz*this.z1.getRuntime() + this.holz*this.z1.getRuntime()*10 + this.holz*this.z1.getRuntime()*10/2;
		//Nichttermination nach 10 Sekunden
		this.stopAll(Math.min(waittime,10000));
	}
	
	//IN: void
	//Out: boolean
	public boolean addRohStaebchen()
	{
		return this.roh.add();
	}
	
	//IN: void
	//Out: boolean
	public boolean addGeschliffenStaebchen()
	{
		return this.geschliffen.add();
	}
	
	//IN: void
	//Out: boolean
	public boolean addVerpacktStaebchen()
	{
		return this.verpackt.add();
	}

	//IN: void
	//Out: boolean
	public boolean getHolz()
	{
		if(this.holz > 0)
		{
			this.holz--;
			return true;
		}
		else
			return false;
	}
	
	//IN: void
	//Out: boolean
	public boolean getgeschliffen()
	{
		return this.geschliffen.take();
	}
	
	//IN: void
	//Out: boolean
	public boolean getroh()
	{
		return this.roh.take();
	}
	
	// Schleifmaschinen stoppen mittels interrupt
	private String stopS()
	{
		String out = "";
		synchronized(this)
		{
			this.s1.interrupt();
			this.s2.interrupt();
			this.s3.interrupt();
			this.s4.interrupt();
			this.s5.interrupt();
			
			//Ausgabe der Stuecke
			if(this.s1.getprocessed()>0)
				out +="\n in S1 vorh. Stueck: "+s1.getprocessed();
			if(this.s2.getprocessed()>0)
				out +="\n in S2 vorh. Stueck: "+s2.getprocessed();
			if(this.s3.getprocessed()>0)
				out +="\n in S3 vorh. Stueck: "+s3.getprocessed();
			if(this.s4.getprocessed()>0)
				out +="\n in S4 vorh. Stueck: "+s4.getprocessed();
			if(this.s5.getprocessed()>0)
				out +="\n in S5 vorh. Stueck: "+s5.getprocessed();
		
			return out;
		}
	}
	
	//Verpackungsmashinen stoppen mittels interrupt
	//IN: void
	//Out: String
	private String stopV()
	{
		String out = "";
		synchronized(this)
		{
			this.v1.interrupt();
			this.v2.interrupt();
			
			//Ausgabe der Stuecke
			if(this.v1.getprocessed()>0)
				out +="\n in v1 vorh. Stueck: "+v1.getprocessed();
			if(this.v2.getprocessed()>0)
				out +="\n in v2 vorh. Stueck: "+v2.getprocessed();
			
			return out;
		}
		
	}
	
	//Zerteilmaschinen stoppen mittels interrupt
	//IN: void
	//Out: String
	private String stopZ()
	{
		synchronized(this)
		{
			this.z1.interrupt();
		}
		
		//Ausgabe der Stuecke
		if(this.z1.getprocessed()>0)
			return "\n in Z1 vorh. Stueck: "+z1.getprocessed();
		else 
			return "";
	}
	
	//Alle Maschinen stoppen, wird automatisch gestoppts falls waittime > 10s
	//IN: long (waittime)
	//Out: void
	public void stopAll(long waittime)
	{
		String out = "";
		//this.interrupt();
		try{
			super.sleep(waittime);
		}
		catch(InterruptedException e)
		{
			return;
		}
		out += this.stopS(); // Schleifmaschinen stoppen
		out += this.stopV(); // Verpackungsmaschinen stoppen
		out += this.stopZ(); // Zerteilmaschinen stoppen
		System.out.println("Systemstatus: ");
		System.out.println("vorh. Holz: "+ this.holz);
		System.out.println("vorh. roh: "+ this.roh.getstock());
		System.out.println("vorh. geschliffen: "+ this.geschliffen.getstock());
		System.out.println("vorh. Packungen: "+ this.verpackt.getstock());
		System.out.println("vorh. Stabechen(2xPackungen): "+ this.verpackt.getstock()*2);

		System.out.println(out);
		
		this.interrupt(); //Fabrik stoppen
	}
}
